<?php

namespace backend\widgets;


use backend\assets\PluploadAsset;
use common\behaviors\FileUsageBehavior;
use Yii;
use yii\base\InvalidConfigException;
use yii\base\InvalidParamException;
use yii\helpers\Html;
use yii\helpers\Json;
use yii\helpers\Url;
use yii\web\JqueryAsset;
use yii\widgets\InputWidget;

class Plupload extends InputWidget
{
    public $dragDrop = true;

    /**
     * @var array
     */
    private $_uploadParams;

    /**
     * @var int 实例数量
     */
    private static $_instanceCount = 0;

    /**
     * @var int 文件数量
     */
    private $_fileCount = 0;

    /**
     * @throws \yii\base\InvalidParamException
     * @throws \yii\base\InvalidConfigException
     */
    public function init()
    {
        parent::init();

        if (!$this->hasModel()) {
            throw new InvalidConfigException('必须设置一个模型。');
        }

        $behavior = $this->model->getBehavior('fileUsage');
        if (!$behavior || !$behavior instanceof FileUsageBehavior) {
            throw new InvalidParamException('模型必须有 FileUsageBehavior 的行为');
        }

        $uploadFields = $this->model->getUploadFields();
        if (!isset($uploadFields[$this->attribute])) {
            throw new InvalidParamException(sprintf('模型的%s不是上传字段属性', $this->attribute));
        }

        $this->_uploadParams = $uploadFields[$this->attribute];

        self::$_instanceCount++;
    }

    /**
     * @inheritdoc
     */
    public function run()
    {
        $this->registerClientScript();
        $many = $this->_uploadParams['many'];
        $pluploadHtmlOptions = array('class' => 'plupload-container', 'id' => 'plupload-container-' . self::$_instanceCount);

        if ($many !== true && $this->_fileCount >= $many) {
            $pluploadHtmlOptions['style'] = 'display: none';
        }

        $button = Html::button('选择' . $this->model->getAttributeLabel($this->attribute), [
                'id' => 'plupload-button-' . self::$_instanceCount, 'class' => 'btn btn-sm btn-primary']);

        if ($this->dragDrop) {
            $output = Html::tag('div', '<div class="drag-drop-inside">
            <div class="info-upload">
            <p class="drag-drop-info">将文件拖到这里</p><p>或</p>
            <p class="drag-drop-buttons">' . $button . '</p>
            </div>
            <div class="info-trash" style="display:none">
            <p class="drag-drop-info">将文件拖到这里将会删除它</p></div></div>
            ', ['id' => 'drag-drop-area-' . self::$_instanceCount, 'class' => 'drag-drop-area']);
        } else {
            $output = $button;
        }

        echo Html::tag('div', $output, $pluploadHtmlOptions);

        if (self::$_instanceCount === 1) {
            echo '<script type="text/javascript">'
                . 'window.YCMF = window.YCMF || {};'
                . 'YCMF.uploaderInit = {};';
        }
        echo "YCMF.uploaderInit[" . self::$_instanceCount . "] = " . Json::encode($this->clientOptions()) . "</script>";
        echo '</script>';
    }

    public function registerClientScript()
    {
        $view = $this->getView();
        PluploadAsset::register($view);
        $view->registerJsFile('@web/js/plupload.js', ['depends' => [
            PluploadAsset::className(),
            JqueryAsset::className(),
        ]]);
    }

    public function clientOptions()
    {
        $type = $this->_uploadParams['type'];
        $many = $this->_uploadParams['many'];

        $extensions = $this->model->getFileExtensionsByField($this->attribute);
        $maxFileSize = strtolower($this->model->getFileMaxSizeByField($this->attribute));

        $name = Html::getInputName($this->model, $this->attribute);
        $options = array(
            'sort' => $this->_uploadParams['sort'],
            'input_id' => $this->options['id'],
            'object' => get_class($this->model),
            'object_id' => $this->model->getPrimaryKey(),
            'many' => $many,
            'plupload' => array(
                'url' => Url::to(['file/upload', 'model' => get_class($this->model), 'field' => $this->attribute]),
                'container' => 'plupload-container-' . self::$_instanceCount,
                'browse_button' => 'plupload-button-' . self::$_instanceCount,
                'drop_element' => 'drag-drop-area-' . self::$_instanceCount,
                'runtimes' => array('html5', 'flash', 'silverlight', 'html4'),
                'multi_selection' => $many !== 1 ? true : false,
                'max_file_size' => $maxFileSize,
                'file_data_name' => $name,
                'multiple_queues' => true,
                'multipart_params' => array(
                    $name => true,
                    'plupload' => true,
                ),
                'filters' => array(
                    array('title' => $type === 'image' ? '图片' : '文件', 'extensions' => $extensions),
                ),
                'headers' => array(
                    'X_REQUESTED_WITH' => 'XMLHttpRequest',
                )
            ),
        );

        $request = Yii::$app->getRequest();
        if ($request->enableCsrfValidation) {
            $options['plupload']['multipart_params'][$request->csrfParam] = $request->getCsrfToken();
        }

        $view = $this->getView();
        $pluploadBundle = $this->getView()->getAssetManager()->getBundle(PluploadAsset::className());

        $pluploadOptions = & $options['plupload'];
        foreach ($pluploadOptions['runtimes'] as $runtime) {
            switch ($runtime) {
                case 'flash':
                    $pluploadOptions['flash_swf_url'] = $view->getAssetManager()->getAssetUrl($pluploadBundle, 'Moxie.swf');
                    break;
                case 'silverlight':
                    $pluploadOptions['silverlight_xap_url'] = $view->getAssetManager()->getAssetUrl($pluploadBundle, 'Moxie.xap');
                    break;
            }
        }
        $pluploadOptions['runtimes'] = implode(',', $pluploadOptions['runtimes']);

        return $options;
    }
} 